/*
 * Copyright (c) 2010, Nikolaus Moll
 * All rights reserved.
 */
package net.miblounge.gradecalculator.core.descriptors.modulelists;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import net.miblounge.gradecalculator.core.descriptors.modulelistitems.IndividualModule;
import net.miblounge.gradecalculator.core.descriptors.modulelistitems.Module;
import net.miblounge.gradecalculator.core.descriptors.modulelistitems.SelectableModuleLists;
import net.miblounge.gradecalculator.core.interfaces.IModuleIdentificator;
import net.miblounge.gradecalculator.core.interfaces.IModuleListItem;

@XmlRootElement(namespace = "http://gradecalculator.net/")
@XmlSeeAlso({Module.class, IndividualModule.class, SelectableModuleLists.class})
@XmlType( 
 propOrder = { "name", "sortOrder", "modules" } 
) 
public class ModuleList implements Comparable<ModuleList>, IModuleIdentificator {
	private String name;
	private List<IModuleListItem> modules;
	private int sortOrder;
	private IModuleIdentificator parent;
	
	public ModuleList() {
		this("");
	}

	public ModuleList(final String name) {
		this.name = name;
		modules = new ArrayList<IModuleListItem>();
	}

	@XmlTransient
	public IModuleIdentificator getParent()
	{
		return parent;
	}
	public void setParent(final IModuleIdentificator parent)
	{
		this.parent = parent;
	}

	@XmlElementWrapper(name="modules")
	@XmlElementRefs({
		    @XmlElementRef(type=Module.class),
		    @XmlElementRef(type=IndividualModule.class),
		    @XmlElementRef(type=SelectableModuleLists.class)
		  })
	public List<IModuleListItem> getModules() {
		return modules;
	}
	public void setModules(final ArrayList<IModuleListItem> modules) {
		this.modules = modules;
	}

	@XmlElement(name = "sortorder")
	public int getSortOrder() {
		return sortOrder;
	}
	public void setSortOrder(final int sortOrder) {
		this.sortOrder = sortOrder;
	}

	@XmlElement(name = "name")
	public String getName() {
		return name;
	}
	public void setName(final String name) {
		this.name = name;
	}

	@Override
	public String getIdentifier() {
		if (parent != null) {
			return parent.getIdentifier() + "." + name;
		}
		return name;
	}
	
	@XmlTransient
	public float getECTS()
	{
		float result = 0;
		for (IModuleListItem i : modules) {
			result += i.getECTS();
		}
		return result;
	}
	
	@XmlTransient
	public int getHoursPerWeek()
	{
		int result = 0;
		for (IModuleListItem i : modules) {
			result += i.getHoursPerWeek();
		}
		return result;
	}
	
	public void addModule(final IModuleListItem module) {
		modules.add(module);
		module.setParent(this);
	}

	public void removeModule(final IModuleListItem module) {
		modules.remove(module);
	}

	@Override
	public int compareTo(final ModuleList moduleList) {
		return this.sortOrder - moduleList.sortOrder;
	}

	@Override
	public String toString()
	{
		return getName();
	}
	
	@Override
	public int hashCode()
	{
		int result = 17;
		result = 31 * result + name.hashCode();
		for (IModuleListItem m : modules) {
			result = 31 * result + m.hashCode();
		}
		
		return result;
	}

	public void invalidate() {
	}

	public void insertModule(final IModuleListItem module, final IModuleListItem moduleBefore) {
		final int index = modules.indexOf(moduleBefore);
		modules.add(index, module);
		module.setParent(this);
	}

}
